package ca.cbc.gis.json;

import ca.cbc.gis.util.GISGeometryBuilder;
import ca.cbc.giscommon.entity.*;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MatchingPois {
    private List<GeoJson> matchingpois;
    private Map<String, Object> bbox;
    private int size;

    public MatchingPois() {
        matchingpois = new ArrayList<GeoJson>();
        size = 0;
    }

    public <T extends BaseEntity> MatchingPois(List<T> items, List<Geometry> defaultBBoxGeometries) {
        this();
        List<Geometry> geometries = this.processItemList(items);
        this.calculateBBox(geometries, defaultBBoxGeometries);
    }

    public MatchingPois(List<Story> stories, List<Content> contents, List<Event> events, List<Tweet> tweets, List<Shape> shapes, List<Geometry> defaultBBoxGeometries) {
        this();
        List<Geometry> geometries = new ArrayList<Geometry>();
        geometries.addAll(this.processItemList(stories));
        geometries.addAll(this.processItemList(contents));
        geometries.addAll(this.processItemList(events));
        geometries.addAll(this.processItemList(shapes));
        geometries.addAll(this.processItemList(tweets));
        this.calculateBBox(geometries, defaultBBoxGeometries);
    }

    private void calculateBBox(List<Geometry> geometries, List<Geometry> defaultBBoxGeometries) {
        if (this.getSize() > 0) { //if find geometries, pass them in to find bbox
            this.bbox = this.getBoundingBox(geometries);
        } else if (defaultBBoxGeometries != null && !defaultBBoxGeometries.isEmpty()) {    //if cannot find geometries and default bounding box geometries are not null, use default one
            this.bbox = this.getBoundingBox(defaultBBoxGeometries);
        }
    }

    private <T extends BaseEntity> List<Geometry> processItemList(List<T> items) {
        List<Geometry> geometries = new ArrayList<Geometry>();
        if (items != null) {
            for (T item : items) {
                matchingpois.add(new GeoJson("Feature", item));
                if (item.getTheGeom() != null)
                    geometries.add(item.getTheGeom());
            }
            this.size += items.size();
        }
        return geometries;
    }

    public Map<String, Object> getBbox() {
        return bbox;
    }

    private Map<String, Object> getBoundingBox(List<Geometry> geometries) {
        Geometry envelope = new GeometryFactory().buildGeometry(geometries).getEnvelope();
        return GISGeometryBuilder.instance.buildGISGeometry(envelope);
    }

    public List<GeoJson> getMatchingpois() {
        return matchingpois;
    }

    public int getSize() {
        return size;
    }

    public void setBbox(Map<String, Object> bbox) {
        this.bbox = bbox;
    }

    public void setMatchingpois(List<GeoJson> matchingpois) {
        this.matchingpois = matchingpois;
    }

    public void setSize(int size) {
        this.size = size;
    }
}
